/*-------------------------------------------------------------------------
 *
 * itemid.h
 *	  标准 POSTGRES 缓冲区页面项标识符/行指针定义。
 *
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/include/storage/itemid.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef ITEMID_H
#define ITEMID_H

/*
 * 缓冲页面上的行指针。有关行指针使用的解释，请参见缓冲页面定义和注释。
 *
 * 在某些情况下，行指针“使用中”但在页面上没有任何关联的存储。
 * 根据约定，在没有存储的每个行指针中，lp_len == 0，与其 lp_flags 状态无关。
 */
typedef struct ItemIdData
{
	unsigned	lp_off:15,		/* 元组的偏移量（从页面开始） */
				lp_flags:2,		/* 行指针的状态，见下文 */
				lp_len:15;		/* 元组的字节长度 */
} ItemIdData;

typedef ItemIdData *ItemId;

/*
 * lp_flags具有这些可能的状态。一个未使用的行指针可立即重新使用，其他状态则不可。
 */
#define LP_UNUSED		0		/* 未使用（应始终具有 lp_len=0） */
#define LP_NORMAL		1		/* 已使用（应始终具有 lp_len>0） */
#define LP_REDIRECT		2		/* HOT 重定向（应具有 lp_len=0） */
#define LP_DEAD			3		/* 死亡，可能有也可能没有存储 */

/*
 * 项目的偏移量和长度在未实际存储在 ItemIdData 中时由这些类型表示。
 */
typedef uint16 ItemOffset;
typedef uint16 ItemLength;


/* ----------------
 *		支持宏
 * ----------------
 */

/*
 *		ItemIdGetLength
 */
#define ItemIdGetLength(itemId) \
   ((itemId)->lp_len)

/*
 *		ItemIdGetOffset
 */
#define ItemIdGetOffset(itemId) \
   ((itemId)->lp_off)

/*
 *		ItemIdGetFlags
 */
#define ItemIdGetFlags(itemId) \
   ((itemId)->lp_flags)

/*
 *		ItemIdGetRedirect
 * 在一个重定向指针中，lp_off 保存下一个行指针的偏移量
 */
#define ItemIdGetRedirect(itemId) \
   ((itemId)->lp_off)

/*
 * ItemIdIsValid
 *		如果项目标识符有效，则为 True。
 *		这是一个非常弱的测试，可能仅在断言中有用。
 */
#define ItemIdIsValid(itemId)	PointerIsValid(itemId)

/*
 * ItemIdIsUsed
 *		如果项目标识符正在使用，则为 True。
 */
#define ItemIdIsUsed(itemId) \
	((itemId)->lp_flags != LP_UNUSED)

/*
 * ItemIdIsNormal
 *		如果项目标识符处于 NORMAL 状态，则为 True。
 */
#define ItemIdIsNormal(itemId) \
	((itemId)->lp_flags == LP_NORMAL)

/*
 * ItemIdIsRedirected
 *		如果项目标识符处于 REDIRECT 状态，则为 True。
 */
#define ItemIdIsRedirected(itemId) \
	((itemId)->lp_flags == LP_REDIRECT)

/*
 * ItemIdIsDead
 *		如果项目标识符处于 DEAD 状态，则为 True。
 */
#define ItemIdIsDead(itemId) \
	((itemId)->lp_flags == LP_DEAD)

/*
 * ItemIdHasStorage
 *		如果项目标识符有相关存储，则为真。
 */
#define ItemIdHasStorage(itemId) \
	((itemId)->lp_len != 0)

/*
 * ItemIdSetUnused
 *		将项目标识符设置为未使用，无存储。
 *		注意对itemId的多次评估！
 */
#define ItemIdSetUnused(itemId) \
( \
	(itemId)->lp_flags = LP_UNUSED, \
	(itemId)->lp_off = 0, \
	(itemId)->lp_len = 0 \
)

/*
 * ItemIdSetNormal
 *		将项目标识符设置为正常，并指定存储。
 *		注意对itemId的多次评估！
 */
#define ItemIdSetNormal(itemId, off, len) \
( \
	(itemId)->lp_flags = LP_NORMAL, \
	(itemId)->lp_off = (off), \
	(itemId)->lp_len = (len) \
)

/*
 * ItemIdSetRedirect
 *		将项目标识符设置为重定向，并指定链接。
 *		注意对itemId的多次评估！
 */
#define ItemIdSetRedirect(itemId, link) \
( \
	(itemId)->lp_flags = LP_REDIRECT, \
	(itemId)->lp_off = (link), \
	(itemId)->lp_len = 0 \
)

/*
 * ItemIdSetDead
 *		将项目标识符设置为死亡，无存储。
 *		注意对itemId的多次评估！
 */
#define ItemIdSetDead(itemId) \
( \
	(itemId)->lp_flags = LP_DEAD, \
	(itemId)->lp_off = 0, \
	(itemId)->lp_len = 0 \
)

/*
 * ItemIdMarkDead
 *		将项目标识符设置为死亡，保留其现有存储。
 *
 * 注意：在索引中，这被用作提示位机制；
 * 我们相信多个处理器可以并行执行此操作并获得
 * 相同结果。
 */
#define ItemIdMarkDead(itemId) \
( \
	(itemId)->lp_flags = LP_DEAD \
)

#endif							/* ITEMID_H */
